import { AnimationClip, Node, SpriteAtlas, tween, Tween, TweenEasing, Vec3 } from 'cc'

/**
 * 创建精灵帧动画剪辑的选项接口
 */
export interface CreateSpriteFrameClipOptions {
	/** 精灵图集 */
	atlas: SpriteAtlas
	/** 动画持续时间(秒) */
	duration: number
	/** 动画剪辑名称 */
	name?: string
	/** 总帧数 */
	frameCount?: number
	/** 帧名称前缀 */
	framePrefix?: string
	/** 是否反向播放 */
	reverse?: boolean
	/** 自定义帧名称序列(设置后会忽略frameCount和framePrefix) */
	frames?: string[]
}
/**
 * 移动动画配置
 */
interface MoveAnimationConfig {
	startPos: Vec3
	endPos: Vec3
	duration?: number
	easing?: TweenEasing
}
/**
 * 晃动动画配置
 */
interface ShakeAnimationConfig {
	distance: number // 晃动幅度
	totalTime: number // 总时长
	shakeCount: number // 摇晃次数
	duration: {
		start: number // 开始时长
		end: number // 结束时长
	}
	easing?: TweenEasing
	direction?: 'horizontal' | 'vertical' // 晃动方向
}

export class AnimationUtils {
	/**
	 * 创建精灵帧动画剪辑
	 */
	static createSpriteFrameClip({
		atlas,
		frameCount,
		duration,
		reverse = false,
		name = '',
		framePrefix = '',
		frames
	}: CreateSpriteFrameClipOptions): AnimationClip {
		const spriteFrames = frames
			? frames.map(frameName => atlas.getSpriteFrame(frameName))
			: Array.from({ length: frameCount }, (_, i) => atlas.getSpriteFrame(`${framePrefix}${i + 1}`))

		const actualFrameCount = frames?.length ?? frameCount
		const frameRate = actualFrameCount / duration

		const clip = AnimationClip.createWithSpriteFrames(
			reverse ? [...spriteFrames].reverse() : spriteFrames,
			frameRate
		)

		clip.name = name
		return clip
	}
	/**
	 * 创建位移动画
	 * @param node 目标节点
	 * @param startPos 起始位置
	 * @param endPos 目标位置
	 * @param duration 动画时长
	 * @param easing 缓动类型
	 *
	 */
	static createMoveAnimation(node: Node, config: MoveAnimationConfig, onComplete?: () => void): void {
		config.duration = config.duration ?? 0.2
		config.easing = config.easing ?? 'quadOut'
		// 设置初始位置
		node.setPosition(config.startPos)
		// 清除现有动画
		Tween.stopAllByTarget(node)

		console
		// 播放位移动画
		tween(node)
			.to(config.duration, { position: config.endPos }, { easing: config.easing })
			.call(() => {
				onComplete?.()
			})
			.start()
	}

	/**
	 * 创建晃动动画
	 * @param node
	 * @param config
	 * @param onComplete
	 */
	static createShakeAnimation(
		node: Node,
		config: ShakeAnimationConfig = {
			distance: 20,
			totalTime: 1.0,
			shakeCount: 8,
			duration: {
				start: 0.08,
				end: 0.08
			},
			easing: 'quadOut',
			direction: 'horizontal'
		},
		onComplete?: () => void
	) {
		const shakeTime = (config.totalTime - config.duration.start - config.duration.end) / config.shakeCount
		const originalPosition = node.position.clone()

		Tween.stopAllByTarget(node)

		const getShakePosition = (distance: number): Vec3 => {
			if (config.direction === 'vertical') {
				return new Vec3(originalPosition.x, originalPosition.y + distance, 0)
			}
			return new Vec3(originalPosition.x + distance, originalPosition.y, 0)
		}

		let tweenSequence = tween(node).to(config.duration.start, { position: getShakePosition(-config.distance) })

		for (let i = 0; i < config.shakeCount; i++) {
			const targetDistance = i % 2 === 0 ? config.distance : -config.distance
			tweenSequence = tweenSequence.to(shakeTime, { position: getShakePosition(targetDistance) })
		}

		tweenSequence
			.to(config.duration.end, { position: originalPosition }, { easing: config.easing })
			.call(() => onComplete?.())
			.start()
	}
}
